#!/usr/bin/env python3
import sys
import re
from collections import Counter, defaultdict, OrderedDict

def main():
    # Read input from stdin
    input_data = sys.stdin.read()

    # Find all classnames
    print("Detecting classnames in the log file...")
    classname_pattern = re.compile(r'\[(\w+)\].*norm=')
    classnames = [match.group(1) for match in classname_pattern.finditer(input_data)
                 if "DEBUG" not in match.group(1)]

    # Count occurrences for all classes
    class_counter = Counter(classnames)
    all_classes = class_counter.most_common()

    # Print all detected classnames with their counts
    print("Detected classnames:")
    for class_name, count in all_classes:
        print(f"{class_name} ({count} entries)")
    print()

    # Use the top 2 classes for comparison (for backward compatibility)
    if len(all_classes) < 2:
        print("Error: Could not find two distinct classnames in the log file")
        return

    class1, class1_count = all_classes[0]
    class2, class2_count = all_classes[1]

    # Extract and compare values
    all_values = defaultdict(dict)
    tag_order = OrderedDict()  # To preserve original order

    # Pattern to match all norm entries from any class
    norm_pattern = re.compile(r'\[(\w+)\]\s+(\S+).*step=(-?\d+).*norm=\s*([0-9]*\.[0-9]+[Ee][\+\-]?[0-9]+|[0-9]*\.?[0-9]+)')

    order_counter = 0
    for match in norm_pattern.finditer(input_data):
        class_name = match.group(1)
        if "DEBUG" in class_name:
            continue

        tag = match.group(2)
        step = match.group(3)
        norm = match.group(4)

        key = f"{tag} (step={step})"

        # Track order of appearance
        if key not in tag_order:
            tag_order[key] = order_counter
            order_counter += 1

        # Store value for this class
        all_values[key][class_name] = norm

    # Determine the maximum tag length for dynamic tag width
    max_tag_length = max([len(tag) for tag in tag_order.keys()]) if tag_order else 40
    tag_width = max(40, max_tag_length + 2)  # Ensure minimum width of 40

    # Print header
    column_width = 15
    header_class_names = [class_name for class_name, _ in all_classes]

    print(f"{'Tag':<{tag_width}} " + " ".join([f"{cn+' Value':<{column_width}}" for cn in header_class_names]) + f" {'Diff (%)':<{column_width}}")
    print(f"{'-'*tag_width:<{tag_width}} " + " ".join([f"{'-'*column_width:<{column_width}}" for _ in header_class_names]) + f" {'-'*column_width:<{column_width}}")

    # Print all entries in original order
    current_step = None
    total_width = tag_width + (len(header_class_names) + 1) * column_width
    separator_line = "-" * total_width

    for tag, _ in sorted(tag_order.items(), key=lambda x: x[1]):
        # Extract step number from the tag
        step_match = re.search(r'step=(-?\d+)', tag)
        if step_match:
            step = int(step_match.group(1))
            if current_step is not None and step != current_step:
                print(separator_line)
            current_step = step

        # Use the full tag without truncation
        display = tag

        values_row = []

        # Get values for each class (or "-" if missing)
        for class_name in header_class_names:
            if class_name in all_values[tag]:
                values_row.append(all_values[tag][class_name])
            else:
                values_row.append("-")

        # Calculate difference percentage (only for class1 and class2)
        if len(all_classes) >= 2:
            class1_val = all_values[tag].get(class1, "-")
            class2_val = all_values[tag].get(class2, "-")

            if class1_val != "-" and class2_val != "-":
                try:
                    class1_num = float(class1_val)
                    class2_num = float(class2_val)

                    if class1_num == 0 and class2_num == 0:
                        diff = "0.00000"
                    elif class1_num == 0:
                        diff = f"{class2_num}"
                    elif class2_num == 0:
                        diff = f"-{class1_num}"
                    else:
                        diff = f"{((class2_num - class1_num) / class1_num * 100):.5f}"
                except ValueError:
                    diff = "-"
            else:
                diff = "-"
        else:
            diff = "-"

        # Print row
        row = f"{display:<{tag_width}} " + " ".join([f"{val:<{column_width}}" for val in values_row]) + f" {diff:<{column_width}}"
        print(row)

    # Print total count of tags in output table
    print(f"\nTotal tags printed in table: {len(tag_order)}")
    
    # Print tags exclusive to each class
    if len(all_classes) >= 2:
        class1_exclusive = []
        class2_exclusive = []
        
        for tag, class_values in all_values.items():
            if class1 in class_values and class2 not in class_values:
                class1_exclusive.append(tag)
            elif class2 in class_values and class1 not in class_values:
                class2_exclusive.append(tag)
        
        if class1_exclusive:
            print(f"\nTags exclusive to {class1}:")
            for tag in sorted(class1_exclusive):
                print(f"  {tag} = {all_values[tag][class1]}")
            
        if class2_exclusive:
            print(f"\nTags exclusive to {class2}:")
            for tag in sorted(class2_exclusive):
                print(f"  {tag} = {all_values[tag][class2]}")

if __name__ == "__main__":
    main()
